package com.dsg.controller.set;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsg.common.constants.DsgStatusConstant;
import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.SingletonLoginUtils;
import com.dsg.common.util.UUIDGenerator;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.entity.apply.DsgApplyCus;
import com.dsg.entity.model.set.DsgSetCusBacklistModel;
import com.dsg.entity.set.DsgSetCusBacklist;
import com.dsg.service.apply.IDsgApplyCusService;
import com.dsg.service.set.IDsgSetCusBacklistService;
import com.dsg.support.LeveldbAccess;
import com.dsg.util.DsgUtils;
import com.dsg.util.RRException;
import com.dsg.util.verify.VerifyHolder;
import com.dsg.util.verify.impl.NotEmptyVerify;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: erp
 * @description:
 * @author: lironglai
 * @create: 2020-08-17 20:30
 */
@Slf4j
public class UploadDsgSetCusBacklist extends AnalysisEventListener<DsgSetCusBacklistModel> {


    private IDsgSetCusBacklistService dsgSetCusBacklistService;
    private IDsgApplyCusService dsgApplyCusService;

    private LeveldbAccess leveldbAccess;

    private List<DsgSetCusBacklist> list = new ArrayList<>();

    private List<String> errorList = new ArrayList();

    private VerifyHolder verifyHolder;

    private Map<String, Integer> idCardMap = new HashMap<>();

    private int totalSize = 1;

    /**
     * 按每1000個一組分割
     */
    private final Integer maxNumber = 1000;
    /**
     * 每隔2条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 3000;

    public UploadDsgSetCusBacklist(IDsgSetCusBacklistService dsgSetCusBacklistService, IDsgApplyCusService dsgApplyCusService,
                                   LeveldbAccess leveldbAccess) {
        this.dsgSetCusBacklistService = dsgSetCusBacklistService;
        this.dsgApplyCusService = dsgApplyCusService;
        this.leveldbAccess = leveldbAccess;
        //数据格式校验
        verifyHolder = new VerifyHolder(DsgSetCusBacklistModel.class, errorList);
        verifyHolder.addVerify(new NotEmptyVerify());
    }

    /**
     * 这个每一条数据解析都会来调用  初始化 进来就要调用到的方法
     *
     * @param dsgSetCusBacklistModel
     * @param analysisContext
     */
    @Override
    public void invoke(DsgSetCusBacklistModel dsgSetCusBacklistModel, AnalysisContext analysisContext) {
        log.info("解析到一條數據:{}", JSONObject.toJSON(dsgSetCusBacklistModel));
        totalSize++;
        try {
            verifyHolder.check(dsgSetCusBacklistModel, totalSize);
        } catch (Exception e) {
            log.error("檢驗數據異常:", e);
            throw new RRException("檢驗數據異常", e);
        }
        DsgSetCusBacklist dsgSetCusBacklist = new DsgSetCusBacklist();
        BeanUtils.copyProperties(dsgSetCusBacklistModel, dsgSetCusBacklist);
        if (!idCardMap.containsKey(dsgSetCusBacklist.getIdCard())) {
            idCardMap.put(dsgSetCusBacklist.getIdCard(), totalSize);
        } else {
            errorList.add(String.format("客戶身份證/公司商業登記證:%s與第%s條重復！", dsgSetCusBacklist.getIdCard(),
                    idCardMap.get(dsgSetCusBacklist.getIdCard())));
        }
        switch (dsgSetCusBacklist.getOwnsType()) {
            case DsgStatusConstant.EXCEL_COM:
                dsgSetCusBacklist.setOwnsType(DsgSetCusBacklist.OWNS_TYPE_COM);
                break;
            case DsgStatusConstant.EXCEL_CUS:
                dsgSetCusBacklist.setOwnsType(DsgSetCusBacklist.OWNS_TYPE_CUS);
                break;
        }
        list.add(dsgSetCusBacklist);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param analysisContext
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (CollectionUtil.isNotEmpty(errorList)) {
            throw new RRException(errorList.toString());
        } else {
            if (CollectionUtil.isNotEmpty(list)) {
                List<String> keyList = new ArrayList<>();
                String oid = UUIDGenerator.getUUID();
                SystemAuthorizingUser user = SingletonLoginUtils.getSystemUser();
                try {
                    List<String> numberList = list.stream().map(DsgSetCusBacklist::getIdCard).collect(Collectors.toList());
                    List<List<String>> splitList = DsgUtils.splitList(numberList, maxNumber);
                    //防止SQL in 超过1000 分割查询后缓存
                    for (List<String> cusNumberList : splitList) {
                        //客戶資料并缓存
                        QueryWrapper<DsgApplyCus> cusQueryWrapper = new QueryWrapper<>();
                        cusQueryWrapper.eq("ENT_CODE", user.getOrgCode());
                        cusQueryWrapper.in("ID_NO", cusNumberList);
                        List<DsgApplyCus> dsgApplyCusList = dsgApplyCusService.list(cusQueryWrapper);
                        dsgApplyCusList.forEach(I -> {
                            String key = leveldbAccess.genCacheKey(oid, DsgApplyCus.class.getSimpleName(), I.getIdNo());
                            leveldbAccess.put(key, I);
                            keyList.add(key);
                        });
                        //黑名單并缓存
                        QueryWrapper<DsgSetCusBacklist> backlistQueryWrapper = new QueryWrapper<>();
                        backlistQueryWrapper.eq("ENT_CODE", user.getOrgCode());
                        backlistQueryWrapper.in("ID_CARD", cusNumberList);
                        List<DsgSetCusBacklist> dsgSetCusBacklistList = dsgSetCusBacklistService.list(backlistQueryWrapper);
                        dsgSetCusBacklistList.forEach(I -> {
                            String key = leveldbAccess.genCacheKey(oid, DsgSetCusBacklist.class.getSimpleName(), I.getIdCard());
                            leveldbAccess.put(key, I);
                            keyList.add(key);
                        });
                    }
                    list.forEach(I -> {
                        I.setOid(UUIDGenerator.getUUID());
                        String key = leveldbAccess.genCacheKey(oid, DsgSetCusBacklist.class.getSimpleName(), I.getIdCard());
                        DsgSetCusBacklist dsgSetCusBacklist = leveldbAccess.get(key);
                        if (dsgSetCusBacklist != null) {
                            errorList.add(String.format("客戶身份證/公司商業登記證%s黑名單已存在", I.getIdCard()));
                        }
                        key = leveldbAccess.genCacheKey(oid, DsgApplyCus.class.getSimpleName(), I.getIdCard());
                        DsgApplyCus dsgApplyCus = leveldbAccess.get(key);
                        if (dsgApplyCus != null) {
                            I.setCusNo(dsgApplyCus.getCusNo());
                            I.setCusId(dsgApplyCus.getOid());
                        }
                    });
                    if (CollectionUtil.isNotEmpty(errorList)) {
                        throw new RRException(String.join(",", errorList));
                    } else {
                        dsgSetCusBacklistService.saveBatch(list);
                    }
                } finally {
                    if (CollectionUtil.isNotEmpty(keyList)) {
                        keyList.forEach(I -> leveldbAccess.delete(I));
                    }
                }

            } else {
                log.info(String.format("無黑名單-客數據"));
                throw new RRException("無黑名單-客數據");
            }
        }
    }
}
